package com.muyu.redisdemo.service.impl;

import com.muyu.redisdemo.common.RedisMediator;
import com.muyu.redisdemo.service.VerificationCodeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName: VerificationCodeServiceImpl
 * @Author: Zirun.Xin
 * @Date: 2025/4/18 上午9:20
 * @Version: 1.0
 * @Description: 验证码业务实现层
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class VerificationCodeServiceImpl implements VerificationCodeService {

    /**
     * redis中介服务
     */
    private final RedisMediator redisMediator;

    /**
     * 验证码发送次数redis缓存键规则
     */
    private static final String COUNT_KEY_RULE = "%s:count";

    /**
     * 验证码redis缓存键规则
     */
    private static final String CODE_KEY_RULE = "%s:code";

    /**
     * 随机获取六位数字
     *
     * @return 随机数
     */
    public String getRandomNum() {
        int number = (int) ((Math.random() * 9 + 1) * 100000);
        return String.valueOf(number);
    }

    /**
     * 获取验证码
     *
     * @param phone 手机号
     * @return 验证码
     */
    @Override
    public String getCode(String phone) {
        // 定义发送次数、验证码、发送间隔时间键标识
        String countKey = String.format(COUNT_KEY_RULE, phone);
        String codeKey = String.format(CODE_KEY_RULE, phone);

        // 每个号码只能发送三次
        String count = redisMediator.get(countKey);

        // 从次数进行判断
        if (count == null) {
            // 说明此号码第一次申请
            // 设置发送次数
            redisMediator.set(countKey, "1", 1, TimeUnit.DAYS);
        } else if (Integer.parseInt(count) <= 2) {
            // 获取当前用户验证码剩余时间
            Long keyExpirationTime = redisMediator.getExpire(countKey);

            // 获取当前次数
            String codeCount = redisMediator.get(countKey);

            // 次数+1
            int newCount = Integer.parseInt(codeCount) + 1;

            //缓存发送次数
            redisMediator.set(countKey, String.valueOf(newCount), keyExpirationTime);
        } else {
            log.warn("当天3次机会用完了！请明日再试");
            return null;
        }

        // 计算发送验证码是否间隔一分钟
        boolean isIntervalTime = redisMediator.hasKey(codeKey) &&
                redisMediator.getExpire(codeKey, TimeUnit.MINUTES) >= TimeUnit.MINUTES.toMinutes(1);
        if (isIntervalTime) {
            log.info("两次获取验证码间隔时间小于1分钟，请稍后重试！");
            return null;
        }

        // 获取随机6位验证码
        String code = this.getRandomNum();

        // 验证码存入redis并设置过期时间 2min
        redisMediator.set(codeKey, code, 2, TimeUnit.MINUTES);

        return code;
    }

    /**
     * 校验验证码
     *
     * @param phone 手机号
     * @param code  验证码
     * @return 是否校验成功
     */
    @Override
    public boolean checkCode(String phone, String code) {
        return Objects.equals(code, redisMediator.get(String.format(CODE_KEY_RULE, phone)));
    }
}
